/*
js数据类型：
基本数据类型（简单数据类型）：number 、string 、Boolean、undefined 、null 、symbol、bigint
复杂数据类型（引用数据类型）：array function object date 正则。。。

ts=typeScript 它是JavaScript超集 最终编译成js在浏览器当中进行渲染
ts中的基本数据类型有哪些：number string Boolean 字面量 any unknown void object array 元组 enum 类型联合 类型断言 类型推断

1.声明类型变'量的格式  关键字可以let  const  var
    1.关键字 变量：数据类型 = 值   let num:number=123
    2.关键字 变量：数据类型； let num:number
      数据类型 = 值          num=123

ts进行类型声明，变量类型声明 形参类型声明、函数返回值类型声明
当指定了类型声明之后，ts编辑器就会根据类型声明声明的类型去自动检查是否符合类型，符合执行代码，不符合报错
当指定类型声明之后，该变量只能存储该类型的值

ts拥有自动的类型判断机制
*/

/*  number  */
let num : number;
num = 111;
// num = '123'  //在上面定义了num是number类型  所以在下面num不能是别的类型
console.log(num);  //111

let num1 :number = 222;
console.log(num1);

/*  string  */
let str1 : string ='hhh';
let str2 : string ='zzz';
let str3 :string;
str3=str1+str2;
console.log(str3); //hhhzzz  字符串拼接
console.log(str1,str2); //hhh   zzz

/*  boolean  */
let bool1 : boolean=true;
console.log(bool1);  //true

/*  使用一个关键字声明多个变量  */
let num2:number , str4:string , bool2:boolean;
num2=789;
str4='好冷';
// str4=123;  当你声明完变量类型时候，你的变量的类型就不能变化，不是该类型就会报错
bool2=true;
console.log(num2,str4,bool2);  //789 好冷 true

let bool3=false;
bool3=true;
// bool3='123';   当变量和赋值是同时进行的，ts就会自动编译变量的数据类型，可以忽略类型声明，但是实际上它声明了类型
console.log(bool3);

/*  字面量  */
let qq='小妹';
qq='小妹';
qq="小米";
console.log(qq);

/*  联合类型  */
let bb : '111' | '米姆' | boolean | 456;
bb=456;
// bb='234';  当赋值是联合类型里面没有的  就会报错
console.log(bb); 

/*  any unknow  
    有时候你不知道这个变量设计为什么数据类型 但是ts必须规定数据类型，如果不写  当声明变量和赋值在一行时ts默认给设置
    
    any 和 unknown  都可以赋值为任意数据类型 ，但是any可以赋值给其他数据类型,unknown不能赋值给其他类型，总结 unknown是安全的

    any不建议使用 能使用unknown就不要使用any
*/

/* any 可以赋值给任意数据类型 */
let cc :any;
cc=999;
// cc='哈哈哈哈哈'; 会覆盖上一个
console.log(cc);

let ff :string;
ff = cc;
console.log(ff);

/* unknown 不能赋值给其他数据类型 */
let ee : unknown;
ee = 777;
ee = true;
let ww : string;
let jj : unknown;
jj = ee;
console.log(ee);

/*  void  函数在ts当中如何写  */

// 函数返回值：当函数内部有return 函数的返回值就是return后面的值，当没有return时，函数的返回值undefined
// 形参需要设计数据类型  函数的返回值需要设计数据类型
// function fun(a,b){
//     return a + b;
// }
// console.log(fun(2,3));  //5

/* function  函数名（形参1：形参1的数据类型，形参2：形参2的数据类型）:函数返回值的数据类型{
    。。。。
    return xxx
} */
function sum(a: number, b: number): number {
    return a + b;
}
console.log(sum(1,1));
// console.log(sum('aa',1));

function foo(a: number, b: string): string {
    return a + b;
}
console.log('yyy',1);
console.log('yyy','iii');

/* void表示没有任何类型，一般用来表示函数的返回值 undefined或者null */
function fun1(a: string, b: number): void {
    let c: string = a + b;
    console.log(c);
    // return '4536';
}
console.log(fun1('aa', 2));

/*  对象  */
let obj:{name:string,age:number};
obj={
    name:'titi',
    age:11
}
console.log(obj);

/* 当对象的数据类型规定完毕后，创建的对象必须严格按照对象规定的数据类型创建，不能多不能少，数据类型也不能不同  */
// let obj1:{name:string,age:number};
// obj1={
//     // name:'ss'
// }

// 让对象中的某个属性可能有可能无  在规定类型时，在属性名后面加?，表示该属性可选   可有可无
let obj1:{name:string,age:number,sex?:string};
obj1={
    name:'hh',
    age:12,
    // sex:"男"
}
console.log(obj1);

// 任意往后面加属性名，但是不知道自己要添加什么属性
let obj2:{name:string,age:number,[propName:string]:unknown};
obj2={
    name:'大大',
    age:78,
    sex:'女',
    hobby:'打麻将'
}
console.log(obj2);

/* array  */

// string[]  表示当前数组的元素类型都为字符串
let arr:string[];
// arr=['zz','xx',123];  报错
arr=['zz','xx','cc'];
console.log(arr); 

// number[]表示当前数组的元素类型都为数字
let arr1:number[];
// arr1=[1,2,3,'1'] 报错
arr1=[1,2,3];
console.log(arr1);

// Array<number> 表示当前数组元素都为number类型
let arr2:Array<number>;
arr2=[2,2,3];
let arr3:Array<string>;
arr3=['kk','ll'];
console.log(arr2,arr3);

/* 元组  */
// 元组类型表示的是一个已知元素数量和类型的数组，各个元素的类型不一定相同
let arr4:[number,string,boolean];
arr4=[123,'ww',false];
console.log(arr4);

/* 枚举  */
// 对数据类型进行一个补充，赋予数据类型一组友好的名字
enum hobby{
    白敬亭,
    王嘉尔,
    王俊凯
}
let ysn:hobby = hobby.王嘉尔;
console.log(ysn,hobby.王嘉尔,hobby.白敬亭);  //1 1 0
console.log(hobby[0]);  //白敬亭

// 手动指定枚举中的值
enum color{
    yellow=2,
    blue,
    black
}
let ysn1:color=color.blue;
console.log(ysn1,color.black); // 3 4
console.log(color['blue']); //3

/* 类型联合  表示取值可以是多种类型 */
let yy:'ysn' | 'nsy' | false;
yy='ysn';
// yy=true;  报错  

function foo1(a:string | number,b:number):void{
    console.log(a,b);
}
foo1('tt',66);

/* 类型断言 手动指定一个值的类型 */
// 方法1：<数据类型>值
// 方法2：值 as 类型  tsx文件中只能使用这种
// 两种方法可以混用

// 当使用了ts规定了数据类型之后，你传入的值必须是该类型的值，如果不是就会报错


function bunn(x:number | string | false){
    if((<string>x).length){
        console.log(111);
        return (<string>x).length;
    }else{
        console.log(222);
        return x.toString().length;
    }
}
console.log(bunn("false"));

function bunn1(x:number | string | false){
    if((x as string).length){
        console.log(111);
        return (<string>x).length;
    }else{
        console.log(222);
        return x.toString().length;
    }
}
console.log(bunn(false));

/* 类型推断 ts中没有明确指定类型时，自动推断出一个数据类型
一种：定义变量并且赋值时，推断为对应的数据类型
二种：定义变量没有赋值时，推断它的类型为any
*/
let app=123;
app=456;
// app='123'; 报错

let app1;
app1=false;
app1=222;


